
/**
* @Title: AtomicStampedReferenceDemo.java
* @Package com.leetone.cas
* @Description: 【】
* @date 2018年3月8日 上午9:36:06
* @version V1.0
* @Company: 上海
* @author:[谭磊][leetone123@163.com]
*/

package com.leetone.cas;

import java.util.concurrent.atomic.AtomicStampedReference;

/**
* @ClassName: AtomicStampedReferenceDemo
* @Description: 【针对AtomicReference加了时间戳，主要针对修改过程敏感的操作】
* @date 2018年3月8日 上午9:36:06
* @Company: 上海
* @author:[谭磊][leetone123@163.com]
*/

public class AtomicStampedReferenceDemo {
	//用户初始余额为19，时间戳为0
	static final AtomicStampedReference<Integer> money = new AtomicStampedReference<Integer>(19, 0);
	/**
	* @Title: main
	* @Description: 【】
	* @date 2018年3月8日 上午9:36:06
	* @author:[谭磊][leetone123@163.com]
	* @param @param args    参数
	* @return void    返回类型
	* @throws
	*/

	public static void main(String[] args) {
		//全局的时间戳，保证充值只有一次
		final int timestamp = money.getStamp();
		//开启3个充值线程,小于20就充值20元，但是只允许充值一次。
		for(int i=0;i<3;i++)
		{
			new Thread() {
				public void run() {
					while(true)
					{
						while(true)
						{
							Integer m = money.getReference();
							if(m<20)
							{
								//开始进行充值20元
								if(money.compareAndSet(m, m+20, timestamp, timestamp+1)) 
								{
									System.out.println("充值20元成功，当前余额为："+money.getReference());
								}
								break;
							}else
							{
//								System.out.println("余额充足，无需充值。");
								break;
							}
						}
					}
				}
			}.start();
		}
		//再开启一个消费线程,每次消费10元
		new Thread() {
			public void run() {
				while(true)
				{
					while(true)
					{
						//局部时间戳，只要余额足够每次都可以进行消费
						int timestamp = money.getStamp();
						Integer m = money.getReference();
						if(m>10)
						{
							if(money.compareAndSet(m, m-10, timestamp, timestamp+1))
							{
								System.out.println("消费成功，当前余额："+money.getReference());
							}
							break;
						}else
						{
							System.out.println("没有足够的余额进行消费");
							break;
						}
					}
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}.start();
	}

}
